using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;

namespace Nate.GUI.Canvas
{
    // Note. Visual Studio really, really doesn't like abstract classes that
    // derive from a form. It tries to bring up the designer view of the file
    // and spews out an error each time it does. Annoying. 
    //
    // My workaround is to make the class non-abstract. While I like the
    // abstract pattern for my use, I can't tolerate the error and warning 
    // messages it will generate.
    public class Base : UserControl, ICanvasControl
    {
        #region Constructor and Public Methods
        public Base()
        {
            _blackboard = new Nate.Shared.Blackboard();

            _refresh_requested = true;
            _timer = new Timer();
            _timer.Interval = 33;
            _timer.Tick += new System.EventHandler(_TimerTick);
            _components = new List<Component.IComponent>();
            _components.Add(new Component.MouseMove(this));
            _components.Add(new Component.MouseZoom(this));
        }

        public override void Refresh()
        {
            _refresh_requested = false;
            base.Refresh();
        }
        #endregion

        #region Interface Implementation
        public void InitCanvas(Control parent, ToolStrip tool_strip)
        {
            // Initialize the component stuff
            _initialize_component();

            // Attach to parent control
            _parent = parent;
            _parent.Controls.Add(this);
            
            // Populate tool strip
            _tool_strip = tool_strip;
            _tool_strip.Items.AddRange(GenerateToolStripItems());

            // Give control a chance to set its initial size.
            Autosize();
        }

        public void TermCanvas()
        {
            if (null != _parent)
            {
                _parent.Controls.Remove(this);
            }

            _tool_strip.Items.Clear();
        }

        public void RefreshCanvas()
        {
            _refresh_requested = true;
        }

        public Shared.Blackboard Blackboard
        {
            get
            {
                return _blackboard;
            }
            set
            {
                _blackboard = value;
            }
        }
        #endregion

        #region Virtual member children must override.
        public    virtual void              ZoomIn() { }
        public    virtual void              ZoomOut() { }
        protected virtual ToolStripItem[]   GenerateToolStripItems() { return null; }
        protected virtual void              HandlePaint(object sender, PaintEventArgs e) { }
        protected virtual void              Autosize() { }
        #endregion

        #region Protected members children may use.
        protected List<Point> Points
        {
            get
            {
                return Blackboard.PathingBB.Path;
            }
        }
        protected Control ParentControl
        {
            get
            {
                return _parent;
            }
        }
        protected List<Component.IComponent> Components
        {
            get
            {
                return _components;
            }
        }
        #endregion

        #region Private data
        private Shared.Blackboard           _blackboard;
        private Control                     _parent;
        private ToolStrip                   _tool_strip;
        private bool                        _refresh_requested;
        private Timer                       _timer;
        private List<Component.IComponent>  _components;

        private const string _default_control_name = "CanvasControl";
        #endregion

        #region private methods
        private void _initialize_component()
        {
            SuspendLayout();

            AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            AutoScaleMode = AutoScaleMode.Font;
            AutoScroll = true;
            DoubleBuffered = true;
            Margin = new Padding(0);
            Name = _default_control_name;
            Paint += new PaintEventHandler(HandlePaint);
            Load += new EventHandler(_Load);

            foreach (Component.IComponent c in _components)
            {
                c.InitializeComponent();
            }

            ResumeLayout(false);
        }
        #endregion

        #region Event Handlers
        private void _Load(object sender, EventArgs e)
        {
            _timer.Start();
        }

        private void _TimerTick(object sender, EventArgs e)
        {
            _timer.Start();

            foreach (Component.IComponent c in _components)
            {
                c.Tick();
            }

            if (_refresh_requested)
            {
                Refresh();
            }
        }
        #endregion
    }
}